package com.letou.ls.uitl;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.text.TextUtils;
import android.util.Base64;
import android.util.DisplayMetrics;


public class ImageUtil {
    /**
     * Utility function for decoding an image resource. The decoded bitmap will be optimized for
     * further scaling to the requested destination dimensions and scaling logic.
     *
     * @param res The resources object containing the image data
     * @param resId The resource id of the image data
     * @param dstWidth Width of destination area
     * @param dstHeight Height of destination area
     * @param scalingLogic Logic to use to avoid image stretching
     * @return Decoded bitmap
     */
    public static Bitmap decodeResource(Resources res, int resId, int dstWidth, int dstHeight,
            ScalingLogic scalingLogic) {
        Options options = new Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, options);
        options.inJustDecodeBounds = false;
        options.inSampleSize = calculateSampleSize(options, dstWidth, dstHeight);
        Bitmap unscaledBitmap = BitmapFactory.decodeResource(res, resId, options);

        return unscaledBitmap;
    }

    /**
     *
     * @param pathName 文件地址
     * @param dstWidth 需要显示的宽度
     * @param dstHeight 需要显示高度
     * @param scalingLogic 缩放类型,crop等比缩放并裁剪,fit原图等比缩放填充
     * @return Decoded bitmap
     */
    public static Bitmap decodeFile(String pathName, int dstWidth, int dstHeight,
            ScalingLogic scalingLogic) {
        if (dstWidth == -1 || dstHeight == -1) {
            return BitmapFactory.decodeFile(pathName);
        }
        Options options = new Options();
        options.inJustDecodeBounds = true;

        BitmapFactory.decodeFile(pathName, options);
        options.inJustDecodeBounds = false;
        options.inSampleSize = calculateSampleSize(options, dstWidth, dstHeight);
        Bitmap unscaledBitmap = BitmapFactory.decodeFile(pathName, options);

        return unscaledBitmap;
    }

    /**
     * Utility function for creating a scaled version of an existing bitmap
     *
     * @param unscaledBitmap Bitmap to scale
     * @param dstWidth Wanted width of destination bitmap
     * @param dstHeight Wanted height of destination bitmap
     * @param scalingLogic Logic to use to avoid image stretching
     * @return New scaled bitmap object
     */
    public static Bitmap createScaledBitmap(Bitmap unscaledBitmap, int dstWidth, int dstHeight,
            ScalingLogic scalingLogic) {
        int srcW = unscaledBitmap.getWidth();
        int srcH = unscaledBitmap.getHeight();

        float rateX = Float.valueOf(dstWidth) / Float.valueOf(unscaledBitmap.getWidth());
        float rateY = Float.valueOf(dstHeight) / Float.valueOf(unscaledBitmap.getHeight());

        Matrix matrix = new Matrix();
        if (rateX < rateY) {
            matrix.postScale(rateX, rateX);
        } else {
            matrix.postScale(rateY, rateY);
        }
        Bitmap newIcon = Bitmap.createBitmap(unscaledBitmap, 0, 0, srcW, srcH, matrix, true);
        // unscaledBitmap.recycle();
        // Rect srcRect = calculateSrcRect(unscaledBitmap.getWidth(),
        // unscaledBitmap.getHeight(), dstWidth, dstHeight, scalingLogic);
        // Rect dstRect = calculateDstRect(unscaledBitmap.getWidth(),
        // unscaledBitmap.getHeight(), dstWidth, dstHeight, scalingLogic);
        // Bitmap scaledBitmap = Bitmap.createBitmap(dstRect.width(),
        // dstRect.height(), Config.ARGB_8888);
        // Canvas canvas = new Canvas(scaledBitmap);
        // canvas.drawBitmap(unscaledBitmap, srcRect, dstRect, new Paint(
        // Paint.FILTER_BITMAP_FLAG));
        return newIcon;
    }



    /**
     * ScalingLogic defines how scaling should be carried out if source and destination image has
     * different aspect ratio.
     *
     * CROP: Scales the image the minimum amount while making sure that at least one of the two
     * dimensions fit inside the requested destination area. Parts of the source image will be
     * cropped to realize this.
     *
     * FIT: Scales the image the minimum amount while making sure both dimensions fit inside the
     * requested destination area. The resulting destination dimensions might be adjusted to a
     * smaller size than requested.
     */
    public static enum ScalingLogic {
        CROP, FIT
    }



    /**
     * Calculates source rectangle for scaling bitmap
     *
     * @param srcWidth Width of source image
     * @param srcHeight Height of source image
     * @param dstWidth Width of destination area
     * @param dstHeight Height of destination area
     * @param scalingLogic Logic to use to avoid image stretching
     * @return Optimal source rectangle
     */
    public static Rect calculateSrcRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight,
            ScalingLogic scalingLogic) {
        if (scalingLogic == ScalingLogic.CROP) {
            final float srcAspect = (float) srcWidth / (float) srcHeight;
            final float dstAspect = (float) dstWidth / (float) dstHeight;

            if (srcAspect > dstAspect) {
                final int srcRectWidth = (int) (srcHeight * dstAspect);
                final int srcRectLeft = (srcWidth - srcRectWidth) / 2;
                return new Rect(srcRectLeft, 0, srcRectLeft + srcRectWidth, srcHeight);
            } else {
                final int srcRectHeight = (int) (srcWidth / dstAspect);
                final int scrRectTop = (srcHeight - srcRectHeight) / 2;
                return new Rect(0, scrRectTop, srcWidth, scrRectTop + srcRectHeight);
            }
        } else {
            return new Rect(0, 0, srcWidth, srcHeight);
        }
    }

    /**
     * Calculates destination rectangle for scaling bitmap
     *
     * @param srcWidth Width of source image
     * @param srcHeight Height of source image
     * @param dstWidth Width of destination area
     * @param dstHeight Height of destination area
     * @param scalingLogic Logic to use to avoid image stretching
     * @return Optimal destination rectangle
     */
    public static Rect calculateDstRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight,
            ScalingLogic scalingLogic) {
        if (scalingLogic == ScalingLogic.FIT) {
            final float srcAspect = (float) srcWidth / (float) srcHeight;
            final float dstAspect = (float) dstWidth / (float) dstHeight;

            if (srcAspect > dstAspect) {
                return new Rect(0, 0, dstWidth, (int) (dstWidth / srcAspect));
            } else {
                return new Rect(0, 0, (int) (dstHeight * srcAspect), dstHeight);
            }
        } else {
            return new Rect(0, 0, dstWidth, dstHeight);
        }
    }

    /**
     * 图片转成string
     *
     * @param bitmap
     * @return
     */
    public static String convertIconToString(Bitmap bitmap) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();// outputstream
        bitmap.compress(CompressFormat.PNG, 100, baos);
        byte[] appicon = baos.toByteArray();// 转为byte数组
        return Base64.encodeToString(appicon, Base64.DEFAULT);

    }

    /**
     * string转成bitmap
     *
     * @param st
     */
    public static Bitmap convertStringToIcon(String st) {
        // OutputStream out;
        Bitmap bitmap = null;
        try {
            // out = new FileOutputStream("/sdcard/aa.jpg");
            byte[] bitmapArray;
            bitmapArray = Base64.decode(st, Base64.DEFAULT);
            bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.length);
            // bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
            return bitmap;
        } catch (Exception e) {
            return null;
        }
    }

    public static Bitmap creatRoundedCornerBitmap(Bitmap bitmap) {
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        float roundPx;
        float left, top, right, bottom, dst_left, dst_top, dst_right, dst_bottom;
        if (width <= height) {
            roundPx = width / 2;
            top = 0;
            bottom = width;
            left = 0;
            right = width;
            height = width;
            dst_left = 0;
            dst_top = 0;
            dst_right = width;
            dst_bottom = width;
        } else {
            roundPx = height / 2;
            float clip = (width - height) / 2;
            left = clip;
            right = width - clip;
            top = 0;
            bottom = height;
            width = height;
            dst_left = 0;
            dst_top = 0;
            dst_right = height;
            dst_bottom = height;
        }
        Bitmap output = Bitmap.createBitmap(width, height, Config.ARGB_8888);
        Canvas canvas = new Canvas(output);
        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect src = new Rect((int) left, (int) top, (int) right, (int) bottom);
        final Rect dst = new Rect((int) dst_left, (int) dst_top, (int) dst_right, (int) dst_bottom);
        final RectF rectF = new RectF(dst);
        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        canvas.drawBitmap(bitmap, src, dst, paint);
        return output;

    }

    public static Bitmap compressImageFromFile(String srcPath) {
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        newOpts.inJustDecodeBounds = true;// 只读边,不读内容
        Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);

        newOpts.inJustDecodeBounds = false;
        int w = newOpts.outWidth;
        int h = newOpts.outHeight;
        float hh = 100f;//
        float ww = 100f;//
        int be = 1;
        if (w > h && w > ww) {
            be = (int) (newOpts.outWidth / ww);
        } else if (w < h && h > hh) {
            be = (int) (newOpts.outHeight / hh);
        }
        if (be <= 0) be = 1;
        newOpts.inSampleSize = be;// 设置采样率

        newOpts.inPreferredConfig = Config.ARGB_8888;// 该模式是默认的,可不设
        newOpts.inPurgeable = true;// 同时设置才会有效
        newOpts.inInputShareable = true;// 。当系统内存不够时候图片自动被回收
        bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
        // return compressBmpFromBmp(bitmap);//原来的方法调用了这个方法企图进行二次压缩
        // 其实是无效的,大家尽管尝试
        return bitmap;
    }

    public static final int COMPRESS_IMAGE_HD_WIDTH = 80;
    public static final int COMPRESS_IMAGE_HD_HEIGHT = 80;
    public static final int COMPRESS_IMAGE_HD_MAX_SIZE = 256; // KB
    public static final int COMPRESS_IMAGE_HD_BASE_QUALITY = 100;
    public static final int COMPRESS_IMAGE_HD_SCALE_SIZE = 10; // KB
    public static final float COMPRESS_IMAGE_HD_SCALE = 0.5f;

    public static boolean compressImageToHD(String srcImageFile, String dstImageFile) {
        return compressImage(srcImageFile, dstImageFile, COMPRESS_IMAGE_HD_MAX_SIZE,
                COMPRESS_IMAGE_HD_BASE_QUALITY, COMPRESS_IMAGE_HD_WIDTH, COMPRESS_IMAGE_HD_HEIGHT);
    }

    public static boolean compressImage(String srcImageFile, String dstImageFile, int maxSize,
            int baseQuality, int reqWidth, int reqHeight) {
        File srcFile = new File(srcImageFile);
        if (!srcFile.exists()) {
            return false;
        }

        BitmapFactory.Options option = new BitmapFactory.Options();
        option.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(srcImageFile, option);

        option.inSampleSize = calculateSampleSize(option, reqWidth, reqHeight);
        option.inJustDecodeBounds = false;
        Bitmap bitmap = BitmapFactory.decodeFile(srcImageFile, option);

        return saveBitmapToPath(bitmap, dstImageFile, CompressFormat.JPEG, maxSize, baseQuality,
                reqWidth, reqHeight);
    }

    public static boolean saveBitmapToPath(Bitmap bitmap, String filePath, CompressFormat format,
            int maxSize, int baseQuality, int reqWidth, int reqHeight) {
        if (TextUtils.isEmpty(filePath)) {
            return false;
        }

        boolean result = false;
        byte[] bytes = bitmapToByteArray(bitmap, format, maxSize, baseQuality, reqWidth, reqHeight);
        if (bytes != null && bytes.length > 0) {
            FileOutputStream outputStream = null;
            try {
                outputStream = new FileOutputStream(filePath);
                outputStream.write(bytes);
                outputStream.flush();
                result = true;
            } catch (FileNotFoundException e) {} catch (IOException e) {} finally {
                if (outputStream != null) {
                    try {
                        outputStream.close();
                    } catch (IOException e) {}
                }
            }
        }
        return result;
    }

    public static Bitmap getCompressBitMap(Bitmap bm, int maxSize, int reqWidth, int reqHeight) {
        byte[] bytes =
                bitmapToByteArray(bm, CompressFormat.JPEG, maxSize, 100, reqWidth, reqHeight);
        if (bytes != null && bytes.length > 0) {
            return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
        }
        return null;
    }

    private static final int MIN_QUALITY = 10;

    public static byte[] bitmapToByteArray(Bitmap bitmap, CompressFormat format, int maxSize,
            int baseQuality, int reqWidth, int reqHeight) {
        if (bitmap == null || bitmap.isRecycled()) {
            return null;
        }

        bitmap = scaleBitmapIfNeed(bitmap, reqWidth, reqHeight);

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        int quality = baseQuality;
        bitmap.compress(format, quality, outputStream);
        byte[] bytes = outputStream.toByteArray();

        if ((format != CompressFormat.PNG) && (0 != maxSize) && (bytes.length / 1024 > maxSize)
                && quality > MIN_QUALITY) {
            do {
                quality -= 10;
                outputStream.reset();
                bitmap.compress(format, quality, outputStream);
                bytes = outputStream.toByteArray();
            } while (bytes.length / 1024 > maxSize && quality > MIN_QUALITY);
        }

        try {
            outputStream.close();
        } catch (IOException e) {}

        return bytes;
    }

    public static Bitmap scaleBitmapIfNeed(Bitmap bitmap, int reqWidth, int reqHeight) {
        if (bitmap == null || bitmap.isRecycled() || reqWidth == -1) {
            return bitmap;
        }

        int width = bitmap.getWidth();
        int height = bitmap.getHeight();

        int newWidth = 0;
        int newHeight = 0;
        if (width > height) {
            newWidth = Math.max(reqWidth, reqHeight);
            newHeight = Math.min(reqWidth, reqHeight);
        } else {
            newWidth = Math.min(reqWidth, reqHeight);
            newHeight = Math.max(reqWidth, reqHeight);
        }

        if (width > newWidth || height > newHeight) {
            bitmap = zoomBitmap(bitmap, newWidth, newHeight);
        }

        return bitmap;
    }

    public static Bitmap zoomBitmap(Bitmap bitmap, int reqWidth, int reqHeight) {
        if (bitmap == null || bitmap.isRecycled()) {
            return bitmap;
        }

        int width = bitmap.getWidth();
        int height = bitmap.getHeight();

        int newWidth = 0;
        int newHeight = 0;
        if (width > height) {
            newWidth = Math.max(reqWidth, reqHeight);
            newHeight = Math.min(reqWidth, reqHeight);
        } else {
            newWidth = Math.min(reqWidth, reqHeight);
            newHeight = Math.max(reqWidth, reqHeight);
        }

        float scale = 0.0f;
        if (width > height) {
            scale = ((float) newWidth) / width;
        } else {
            scale = ((float) newHeight) / height;
        }

        Matrix matrix = new Matrix();
        matrix.postScale(scale, scale);

        // recreate the new Bitmap
        return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
    }

    public static int calculateSampleSize(BitmapFactory.Options options, int reqWidth,
            int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {
            
            // Calculate ratios of height and width to requested height and
            // width
            final int heightRatio = Math.round((float) height / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);

            // Choose the smallest ratio as inSampleSize value, this will
            // guarantee a final image
            // with both dimensions larger than or equal to the requested height
            // and width.
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;

            // This offers some additional logic in case the image has a strange
            // aspect ratio. For example, a panorama may have a much larger
            // width than height. In these cases the total pixels might still
            // end up being too large to fit comfortably in memory, so we should
            // be more aggressive with sample down the image (=larger
            // inSampleSize).

            final float totalPixels = width * height;

            // Anything more than 2x the requested pixels we'll sample down
            // further
            final float totalReqPixelsCap = reqWidth * reqHeight * 2;

            while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
                inSampleSize++;
            }
        }
        return inSampleSize;
    }

    private final static int WIDTH = 70;
    private final static float PADDING_PARAM = (float) 10 / 100;
    private final static float SHADE_PARAM = (float) 8 / 100;

    private final static int CIRCLE_COLOR = Color.WHITE;
    private final static int BORDER_COLOR = Color.argb((int) (0.2 * 256), 0, 0, 0);

    public static Bitmap createCircleBitmap(Context context) {
        Paint paint = new Paint();
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.FILL); // 设置为实心的
        paint.setColor(CIRCLE_COLOR);
        paint.setStrokeWidth(1);

        DisplayMetrics dm = context.getResources().getDisplayMetrics();
        float density = dm.density; // 屏幕密度（像素比例：0.75/1.0/1.5/2.0）
        // int densityDPI = dm.densityDpi; // 屏幕密度（每寸像素：120/160/240/320）

        int width = (int) (UiSizeHelper.scalePx(context, WIDTH) * density);
        int height = width;// (int) (Config.scalePx(context, WIDTH) * density);

        // Log.d("scr", "create screenWidth=" + screenWidth + " width=" + width
        // + " height=" +
        // height);

        int padding = (int) (height * PADDING_PARAM);
        float mCircleRadius = (height - padding * 2) / 2f;

        PointF mCirclePointF = new PointF();
        mCirclePointF.set(width / 2f, height / 2f);
        Bitmap bitmap = null;
        try {
            bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        } catch (OutOfMemoryError e) {} catch (Exception e) {}
        if (bitmap == null) {
            return null;
        }
        Canvas canvas = new Canvas(bitmap);

        paint.setColor(CIRCLE_COLOR);
        paint.setStyle(Paint.Style.FILL);
        paint.setStrokeWidth(1);
        paint.setShadowLayer(mCircleRadius * SHADE_PARAM, 0, mCircleRadius * SHADE_PARAM * 2,
                BORDER_COLOR);
        canvas.drawCircle(mCirclePointF.x, mCirclePointF.y, mCircleRadius, paint);

        paint.setColor(BORDER_COLOR);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(1 * density);
        paint.clearShadowLayer();
        canvas.drawCircle(mCirclePointF.x, mCirclePointF.y, mCircleRadius, paint);

        canvas.save();
        canvas.restore();
        return bitmap;
    }

    public static Bitmap createCircleBitmap(Context context, int color) {
        
        Paint paint = new Paint();
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.FILL); // 设置为实心的
        paint.setColor(color);
        paint.setStrokeWidth(1);

        DisplayMetrics dm = context.getResources().getDisplayMetrics();
        float density = dm.density; // 屏幕密度（像素比例：0.75/1.0/1.5/2.0）
        // int densityDPI = dm.densityDpi; // 屏幕密度（每寸像素：120/160/240/320）

        int width = (int) (UiSizeHelper.scalePx(context, WIDTH) * density);
        int height = width;// (int) (Config.scalePx(context, WIDTH) * density);

        // Log.d("scr", "create screenWidth=" + screenWidth + " width=" + width
        // + " height=" +
        // height);

        int padding = (int) (height * PADDING_PARAM);
        float mCircleRadius = (height - padding * 2) / 2f;

        PointF mCirclePointF = new PointF();
        mCirclePointF.set(width / 2f, height / 2f);
        Bitmap bitmap = null;
        try {
            bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        } catch (OutOfMemoryError e) {} catch (Exception e) {}
        if (bitmap == null) {
            return null;
        }
        Canvas canvas = new Canvas(bitmap);

        paint.setColor(color);
        paint.setStyle(Paint.Style.FILL);
        paint.setStrokeWidth(1);
        paint.setShadowLayer(mCircleRadius * SHADE_PARAM, 0, mCircleRadius * SHADE_PARAM * 2,
                BORDER_COLOR);
        canvas.drawCircle(mCirclePointF.x, mCirclePointF.y, mCircleRadius, paint);

        paint.setColor(BORDER_COLOR);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(1 * density);
        paint.clearShadowLayer();
        canvas.drawCircle(mCirclePointF.x, mCirclePointF.y, mCircleRadius, paint);

        canvas.save();
        canvas.restore();

        return bitmap;
    }

    public static BitmapDrawable createCircleDrawable(Context context) {
        BitmapDrawable drawable = null;
        Bitmap bitmap = createCircleBitmap(context);
        if (bitmap != null) {
            drawable = new BitmapDrawable(context.getResources(), bitmap);
        }
        return drawable;
    }
    
    
    
}
